package com.zhuxi.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Activate(group = CommonConstants.CONSUMER)
public class TPMonitorFilter implements Filter,Runnable {

    private Map<String, List<MethodCost>> methodCostsMap = new HashMap<>();

    public TPMonitorFilter() {
        Executors.newSingleThreadScheduledExecutor().
                scheduleWithFixedDelay(this,5,5, TimeUnit.SECONDS);
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//        System.out.println("拦截方法"+invocation.getServiceName()+"."+invocation.getMethodName());
        long startTime = System.currentTimeMillis();
        Result result = invoker.invoke(invocation);
        long endTime = System.currentTimeMillis();
        long costTime = endTime - startTime;
        MethodCost methodCost = new MethodCost(invocation.getMethodName(),costTime,endTime);
        List<MethodCost> methodCosts = methodCostsMap.get(invocation.getMethodName());
        if (methodCosts == null) {
            methodCosts = new ArrayList<>();
            methodCostsMap.put(invocation.getMethodName(),methodCosts);
        }
        methodCosts.add(methodCost);
        //如果达到一分钟，将一分钟前的数据移除，只保存最近一分钟的
        if (endTime - methodCosts.get(0).getEndTime() > 60000) {
            methodCosts.remove(methodCosts.get(0));
        }
//        System.out.println(methodCosts.get(0).getMethodName()+"----"+methodCosts.get(0));
        return result;
    }

    @Override
    public void run() {
        System.out.println("==========================TP90 TP99监控===========================");
        for (Map.Entry<String, List<MethodCost>> stringListEntry : methodCostsMap.entrySet()) {
            List<MethodCost> methodCosts = stringListEntry.getValue();
            System.out.println("方法"+stringListEntry.getKey()+"调用了"+methodCosts.size()+"次，TP90统计结果为：" + getTPXX(methodCosts, 0.9f));
            System.out.println("方法"+stringListEntry.getKey()+"调用了"+methodCosts.size()+"次，TP99统计结果为：" + getTPXX(methodCosts, 0.99f));
        }
    }

    private static long getTPXX(List<MethodCost> methodCosts, float count) {
        List<MethodCost> sortedMethodCosts = new ArrayList<>();
        sortedMethodCosts.addAll(methodCosts);
        Collections.sort(sortedMethodCosts, new Comparator<MethodCost>() {
            @Override
            public int compare(MethodCost o1, MethodCost o2) {
                if (o1.getCostTime() - o2.getCostTime() > 0) {
                    return 1;
                } else if (o1.getCostTime() - o2.getCostTime() < 0) {
                    return -1;
                } else {
                    return 0;
                }

            }
        });
        int index = (int) (sortedMethodCosts.size() * count);
        return sortedMethodCosts.get(index).getCostTime();
    }

}
